package tech.yunland.shop.domain.dao;

import com.moyuer.bsf.domain.dao.BaseDao;
import com.moyuer.bsf.domain.model.User;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;
import tech.yunland.shop.domain.model.*;
import tech.yunland.shop.domain.model.report.Commission;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 提成明細DAO
 *
 * @author 王睿智<geekrize@gmail.com>
 *
 */

@Repository
public class CommissionDao extends BaseDao<Commission, String> {

	@Autowired
	private JobPrizeDao jobPrizeDao;
	@Autowired
	private UserPrizeDao userPrizeDao;
	@Autowired
	private GoodsDao goodsDao;
	@Autowired
	private GoodsPaidDao goodsPaidDao;
	@Autowired
    private SessionFactory sessionFactory;

	/**
	 * 销售单提成(按照员工占比分配固定提成额度)
	 *
	 * @param saleBill
	 */
	public void addSaleJob(SaleBill saleBill) {

		// 参数
		BigDecimal goodsRate = BigDecimal.ZERO;
		BigDecimal sumGoodsPrice = BigDecimal.ZERO;
		BigDecimal sumCommission = BigDecimal.ZERO;
		Commission commission = null;
		GoodsPaid memberPrice = null;

		// 取出计算参数
		for (SaleBillEntry saleBillEntry : saleBill.getEntries()) {

			Goods goods = goodsDao.get(saleBillEntry.getGoods().getId());
			sumGoodsPrice = sumGoodsPrice.add(goods.getPrice().multiply(saleBillEntry.getQuantity()));

			if (saleBillEntry.getHandlers() != null) {
				for (SaleBillHandler saleBillHandler : saleBillEntry.getHandlers()) {

					/*--员工的提成比率合计--*/
					BigDecimal jp = jobPrizeDao.getJobpPrize(saleBill.getOrganId(), saleBillHandler.getJobId());
					sumCommission = sumCommission.add(jp);
				}
			}
		}

		// 根据实收计算商品折扣率
		goodsRate = saleBill.getReceived().divide(sumGoodsPrice, 8, BigDecimal.ROUND_HALF_UP);

		// 向提成表中添加数据
		for (SaleBillEntry saleBillEntry : saleBill.getEntries()) {

			Goods goods = goodsDao.get(saleBillEntry.getGoods().getId());
			BigDecimal received = (goods.getPrice().multiply(saleBillEntry.getQuantity())).multiply(goodsRate);// 实收金额

			if (saleBillEntry.getHandlers() != null) {

				for (SaleBillHandler saleBillHandler : saleBillEntry.getHandlers()) {

					BigDecimal prize = BigDecimal.ZERO;// 商品实际单价
					BigDecimal receivedGoodPrize = BigDecimal.ZERO;// 现金商品实际提成
					BigDecimal memberGoodPrize = BigDecimal.ZERO;// 会员扣卡商品实际提成
					BigDecimal couponGoodPrize = BigDecimal.ZERO;// 代金券商品实际提成

					// 判断支付方式用于计算商品实际单价
					if (saleBill.getPayment() == 10) {
						memberPrice = goodsPaidDao.getMemberPrizeBySql(saleBillEntry.getGoods().getId().toString(),
								saleBill.getOrgan().getId().toString(), saleBill.getMember().getId().toString());
						BigDecimal zero = memberPrice.getAmount().setScale(0, BigDecimal.ROUND_DOWN);
						if (zero.equals(BigDecimal.ZERO)) {
							prize = BigDecimal.ZERO;
						} else {
							prize = memberPrice.getAmount().divide(memberPrice.getQuantity(), 16, BigDecimal.ROUND_HALF_UP);
						}
//						prize = memberPrice.getAmount().divide(memberPrice.getQuantity(), 16, BigDecimal.ROUND_HALF_UP);
					} else if (saleBill.getPayment() == 20 || saleBill.getPayment() == 60 || saleBill.getPayment() == 70 || saleBill.getPayment() == 80) {
						prize = received;
					} else if (saleBill.getPayment() == 40) {
//						memberPrice = goodsPaidDao.getMemberPrizeBySql(Goods.DJQ_ID,
//								saleBill.getOrgan().getId().toString(), saleBill.getMember().getId().toString());
//						prize = memberPrice.getAmount().divide(memberPrice.getQuantity(), 16, BigDecimal.ROUND_HALF_UP);
					} else if (saleBill.getPayment() == 30) {
						prize = BigDecimal.ZERO;
					}

					BigDecimal ratio = goods.getPrize().divide(goods.getPrice(), 16, BigDecimal.ROUND_HALF_UP);// 商品提成比率
					receivedGoodPrize = received.multiply(ratio);// 现金商品实际提成
					memberGoodPrize = prize.multiply(ratio);// 会员扣卡商品实际提成
//					couponGoodPrize = saleBill.getReceived().multiply(prize).multiply(ratio);// 代金券商品实际提成
					couponGoodPrize = saleBill.getReceived().multiply(ratio);// 代金券商品实际提成

					// 判断支付类型(10扣卡.20现金.30积分.40代金券)
					if (saleBillEntry.getPayment() == 10) {
						prize = memberGoodPrize;
					} else if (saleBillEntry.getPayment() == 20 || saleBill.getPayment() == 60 || saleBill.getPayment() == 70 || saleBill.getPayment() == 80) {
						prize = receivedGoodPrize;
					} else if (saleBillEntry.getPayment() == 30) {

					} else if (saleBillEntry.getPayment() == 40) {
						prize = couponGoodPrize;
					}

					DetachedCriteria criteria = DetachedCriteria.forClass(Commission.class);
					criteria.add(Restrictions.eq("organId", saleBill.getOrgan().getId()));
					criteria.add(Restrictions.eq("bizDate", saleBill.getBizdate()));
					criteria.createCriteria("user").add(Restrictions.idEq(saleBillHandler.getHandler().getId()));
					List<Commission> list = this.findByCriteria(criteria);

					BigDecimal jp = jobPrizeDao.getJobpPrize(saleBill.getOrganId(), saleBillHandler.getJobId());// 员工提成

					if (prize.equals(BigDecimal.ZERO)) {
						// 商品提成没有设置不进行计算
					} else {

                        int size = saleBillEntry.getHandlers().size(); //经手人个数
                        // 没有历史记录新增
						if (list == null || list.size() == 0) {

							commission = new Commission();
							commission.setBizDate(saleBill.getBizdate());
							commission.setOrganId(saleBill.getOrgan().getId());
							commission.setUser(saleBillHandler.getHandler());
							commission.setCharge(BigDecimal.ZERO);
							commission.setSale(saleBillEntry.getAmount().divide(BigDecimal.valueOf(size),8, BigDecimal.ROUND_HALF_UP));
							BigDecimal jobPrize = jp.divide(sumCommission, 8, BigDecimal.ROUND_HALF_UP);
							BigDecimal prizeValue = jobPrize.setScale(8, BigDecimal.ROUND_HALF_UP);
							commission.setCommission(prize.multiply(prizeValue).setScale(2, BigDecimal.ROUND_HALF_UP));
							this.save(commission);

							// 有历史记录相加
						} else if (list.size() == 1) {

							commission = new Commission();
							commission = list.get(0);
							commission.setSale(commission.getSale().add(saleBillEntry.getAmount().divide(BigDecimal.valueOf(size),8, BigDecimal.ROUND_HALF_UP)));
							BigDecimal jobPrize = jp.divide(sumCommission, 8, BigDecimal.ROUND_HALF_UP);
							BigDecimal prizeValue = jobPrize.setScale(8, BigDecimal.ROUND_HALF_UP);
							commission.setCommission(commission.getCommission()
									.add(prize.multiply(prizeValue).setScale(2, BigDecimal.ROUND_HALF_UP)));
						}
						this.save(commission);
					}
				}
			}
		}
	}

	/**
	 * 充值单提成（按照个人比率提成）
	 *
	 * @param saleBill
	 */
	public void addChangeUser(SaleBill saleBill) {
		// TODO 暂未实现充值单个人比率

	}

	public void byUserSale(SaleBill saleBill) {
		// 判断当前单据是否是会员消费 true 会员消费 false 非会员消费
		boolean flag = false;
		if (saleBill.getMember() != null) {
			flag = true;
		}

		for (SaleBillEntry saleBillEntry : saleBill.getEntries()) {// 遍历分录信息以获取
			if (saleBillEntry.getHandlers() != null) {// 如果有员工的话则给员工计算提成
				this.calcCommission(saleBillEntry.getHandlers(), flag, saleBill, saleBillEntry);// 计算提成
			}
		}
	}

	/**
	 * 计算提成
	 * 
	 * @param handlers
	 *            经手人列表
	 * @param flag
	 *            否是会员消费 true 会员消费 false 非会员消费
	 */ 
	private void calcCommission(Set<SaleBillHandler> handlers, boolean flag, SaleBill saleBill,
			SaleBillEntry saleBillEntry) {

		String organId = saleBill.getOrgan().getId();// 拿到订单所属机构
		Date bizDate = saleBill.getBizdate(); // 拿到当前订单的日期

		int handlerSize = handlers.size();
		for (SaleBillHandler saleBillHandler : handlers) {// 遍历处理当前订单的员工以计算提成
			String handleId = saleBillHandler.getHandler().getId(); // 员工ID
			Commission currentUserCommission = getCurrentUserCommission(organId, bizDate, handleId);// 获取当前员工的历史提成
																									// 如果为空则表示此员工之间无提成
			List<UserPrize> currentUserPrize = getCurrentUserPrize(organId, handleId); // 获取为当前员工设置的提成信息

			BigDecimal prize = BigDecimal.ZERO;// 商品实际单价
			Goods goods = goodsDao.get(saleBillEntry.getGoods().getId());// 获取当前

			Map<String, BigDecimal> memberConsumer = this.memberConsumer(saleBill, saleBillEntry, goods);

			prize = memberConsumer.get("prize");

			if (currentUserCommission == null) {// 如果该员工当天还没有提成 则进行当前提成新增
				this.setAddCommission(currentUserPrize, saleBillHandler, saleBillEntry, organId, prize, goods,
						saleBill.getReceived(),handlerSize);
			} else {// 如果已经有提成则进行累加
				this.setPlusCommission(currentUserPrize, saleBillEntry, prize, goods, currentUserCommission,
						saleBill.getReceived(),handlerSize);
			}

		}
	}

	/**
	 * 为员工进行提成累加
	 *  @param currentUserPrize
	 * @param saleBillEntry
	 * @param prize
	 * @param goods
	 * @param currentUserCommission
	 * @param handlerSize
	 */
	private void setPlusCommission(List<UserPrize> currentUserPrize, SaleBillEntry saleBillEntry, BigDecimal prize,
								   Goods goods, Commission currentUserCommission, BigDecimal received, int handlerSize) {
		if (currentUserPrize == null || currentUserPrize.size() == 0) {// 如果该员工没有设置提成
			return;
		}

		UserPrize userPrize = currentUserPrize.get(0);
		Integer prizeType = userPrize.getPrizeType();
		BigDecimal prizeValue = userPrize.getPrizeValue();
		BigDecimal newCommission = BigDecimal.ZERO;
		BigDecimal newSale = BigDecimal.ZERO;
		// 判断提成类型
		if (prizeType == 10) {// 固定金额
			newCommission = prizeValue.add(currentUserCommission.getCommission());
			newSale = prizeValue.add(saleBillEntry.getAmount().divide(BigDecimal.valueOf(handlerSize),BigDecimal.ROUND_HALF_UP));
			newSale = newSale.setScale(2, BigDecimal.ROUND_HALF_UP);
			newCommission = newCommission.setScale(2, BigDecimal.ROUND_HALF_UP);
		} else if (prizeType == 20) {// 百分比
			newCommission = currentUserCommission.getCommission().add(prize.multiply(prizeValue));
			newSale = currentUserCommission.getSale().add(saleBillEntry.getAmount().divide(BigDecimal.valueOf(handlerSize),BigDecimal.ROUND_HALF_UP));
			newSale = newSale.setScale(2, BigDecimal.ROUND_HALF_UP);
			newCommission = newCommission.setScale(2, BigDecimal.ROUND_HALF_UP);
		}
		this.updateUserCommission(newSale, newCommission, currentUserCommission.getId());
	}

	private void updateUserCommission(BigDecimal newSale, BigDecimal newCommission, String id) {
		Session s = this.getSession();
		String sql = "UPDATE rpt_commission set sale = " + newSale + ",commission =" + newCommission + " where id ='"
				+ id + "'";
		SQLQuery query = s.createSQLQuery(sql);
		query.executeUpdate();
	}

	/**
	 * 为员工增加当天的提成信息
	 *  @param currentUserPrize
	 *            当前员工的提成设置
	 * @param saleBillHandler
	 *            单据处理人
	 * @param saleBillEntry
 *            单据信息
	 * @param organId
*            机构ID
	 * @param prize
*            提成
	 * @param goods
	 * @param handlerSize
	 */
	private void setAddCommission(List<UserPrize> currentUserPrize, SaleBillHandler saleBillHandler,
								  SaleBillEntry saleBillEntry, String organId, BigDecimal prize, Goods goods, BigDecimal received, int handlerSize) {
		Commission commission = null;

		// 判断是否设置提成
		if (currentUserPrize == null || currentUserPrize.size() == 0) {
			return;
		}
		commission = new Commission();
		User handler = saleBillHandler.getHandler();
		commission.setOrganId(organId);
		commission.setUser(handler);
		commission.setCharge(BigDecimal.ZERO);
		// 获取提成类型
		UserPrize userPrize = currentUserPrize.get(0);
		Integer prizeType = userPrize.getPrizeType();
		BigDecimal prizeValue = userPrize.getPrizeValue();

		// 判断提成类型
		if (prizeType == 10) {// 固定金额
			BigDecimal newCommission = prizeValue;
			BigDecimal newSale = prizeValue;
			commission.setSale(prize.divide(BigDecimal.valueOf(handlerSize),BigDecimal.ROUND_HALF_UP));
			commission.setCommission(newCommission.setScale(2, BigDecimal.ROUND_HALF_UP));
		} else if (prizeType == 20) {// 百分比
			BigDecimal newCommission = prize.multiply(prizeValue);
			commission.setSale(saleBillEntry.getAmount().divide(BigDecimal.valueOf(handlerSize),BigDecimal.ROUND_HALF_UP));
			commission.setCommission(newCommission.setScale(2, BigDecimal.ROUND_HALF_UP));
		}
		Session session =  sessionFactory.openSession();
		Transaction tran = session.beginTransaction();
		//this.save(commission);
		session.save(commission);
		tran.commit();

	}

	/**
	 * 会员消费
	 * 
	 * @param saleBill
	 * @param saleBillEntry
	 */
	private Map<String, BigDecimal> memberConsumer(SaleBill saleBill, SaleBillEntry saleBillEntry, Goods goods) {
		Map<String, BigDecimal> _result = new HashMap<>();
		BigDecimal prize = BigDecimal.ZERO;// 商品实际单价
		BigDecimal receivedGoodPrize = BigDecimal.ZERO;// 现金商品实际提成
		BigDecimal memberGoodPrize = BigDecimal.ZERO;// 会员扣卡商品实际提成
		BigDecimal couponGoodPrize = BigDecimal.ZERO;// 代金券商品实际提成

		BigDecimal sumGoodsPrice = BigDecimal.ZERO;// 商品原价合计
		BigDecimal goodsRate = BigDecimal.ZERO;// 实收商品折扣率
		// 计算商品原价合计
		for (SaleBillEntry addGoodsPrice : saleBill.getEntries()) {
			Goods good = goodsDao.get(addGoodsPrice.getGoods().getId());
			sumGoodsPrice = sumGoodsPrice.add(good.getPrice().multiply(addGoodsPrice.getQuantity()));
		}
		// 根据实收计算商品折扣率
		goodsRate = saleBill.getReceived().divide(sumGoodsPrice, 8, BigDecimal.ROUND_HALF_UP);
		BigDecimal received = (goods.getPrice().multiply(saleBillEntry.getQuantity())).multiply(goodsRate);// 实收金额

		String orginId = saleBill.getOrgan().getId(); // 机构ID
		String goodId = goods.getId(); // 商品ID
		String memberId = null;
		if (saleBill.getMember() != null) {
			memberId = saleBill.getMember().getId();
		}

		// 判断支付方式用于计算商品实际单价
		if (saleBill.getPayment() == 10) {

			GoodsPaid gp = goodsPaidDao.getMemberPrizeBySql(goodId, orginId, memberId);
			BigDecimal zero = gp.getAmount().setScale(0, BigDecimal.ROUND_DOWN);
			if (zero.equals(BigDecimal.ZERO)) {
				prize = BigDecimal.ZERO;
			} else {
				prize = gp.getAmount().divide(gp.getQuantity(), 16, BigDecimal.ROUND_HALF_UP);
			}

		} else if (saleBill.getPayment() == 20 || saleBill.getPayment() == 60 || saleBill.getPayment() == 70 || saleBill.getPayment() == 80) {

			prize = received;
		} else if (saleBill.getPayment() == 40) {
//			GoodsPaid gp = goodsPaidDao.getMemberPrizeBySql(Goods.DJQ_ID, orginId, memberId);
//			prize = gp.getAmount().divide(gp.getQuantity(), 2, BigDecimal.ROUND_HALF_UP);
		} else if (saleBill.getPayment() == 30) {
			prize = BigDecimal.ZERO;
		}

		BigDecimal ratio = goods.getPrize().divide(goods.getPrice(), 16, BigDecimal.ROUND_HALF_UP);// 商品提成比率
		receivedGoodPrize = received.multiply(ratio);// 现金商品实际提成
		memberGoodPrize = prize.multiply(ratio);// 会员扣卡商品实际提成
//		couponGoodPrize = received.multiply(prize).multiply(ratio);// 代金券商品实际提成
		couponGoodPrize = received.multiply(ratio);// 代金券商品实际提成

		// 判断支付类型(10扣卡.20现金.30积分.40代金券)
		if (saleBillEntry.getPayment() == 10) {
			if (prize.equals(BigDecimal.ZERO)) {
				prize = BigDecimal.ZERO;
			} else {
				prize = memberGoodPrize;
			}
		} else if (saleBillEntry.getPayment() == 20|| saleBillEntry.getPayment() == 60 || saleBillEntry.getPayment() == 70 || saleBillEntry.getPayment() == 80) {
			prize = receivedGoodPrize;
		} else if (saleBillEntry.getPayment() == 30) {

		} else if (saleBillEntry.getPayment() == 40) {
			prize = couponGoodPrize;
		} else {

		}
		_result.put("prize", prize);

		return _result;
	}

	/**
	 * 获取当前员工的提成信息
	 * 
	 * @param organId
	 * @param handleId
	 * @return
	 */
	private List<UserPrize> getCurrentUserPrize(String organId, String handleId) {

		DetachedCriteria criteriaUser = DetachedCriteria.forClass(UserPrize.class);
		criteriaUser.createCriteria("owner").add(Restrictions.idEq(handleId));
		criteriaUser.add(Restrictions.eq("organId", organId));
		criteriaUser.add(Restrictions.eq("state", 1));

		List<UserPrize> prizeList = userPrizeDao.findByCriteria(criteriaUser);
		return prizeList;
	}

	/**
	 * 获取当前员工的提成记录
	 * 
	 * @param organId
	 *            当前机构ID
	 * @param bizDate
	 *            提成日期
	 * @param handleId
	 *            当前员工ID
	 * @return
	 */
	private Commission getCurrentUserCommission(String organId, Date bizDate, String handleId) {
		String sql = "select * from rpt_commission where organ_id = ? and user_id = ? and biz_date = ?";
		Map<String, Object> mapCommission = this.findUniqueBySQL(sql, new Object[] { organId, handleId, bizDate });
		if (mapCommission == null) {
			return null;
		}
		Commission c = new Commission();
		c.setId("");// 先将生成的ID置为空
		String strCommission = ObjectUtils.getDisplayString(mapCommission.get("commission"));
		if (StringUtils.isNotBlank(strCommission)) {
			c.setCommission(new BigDecimal(strCommission));
		}
		String strID = ObjectUtils.getDisplayString(mapCommission.get("id"));
		if (StringUtils.isNotBlank(strID)) {
			c.setId(strID);
		}
		String strSale = ObjectUtils.getDisplayString(mapCommission.get("sale"));
		if (StringUtils.isNotBlank(strSale)) {
			c.setSale(new BigDecimal(strSale));
		}
		String strCharge = ObjectUtils.getDisplayString(mapCommission.get("charge"));
		if (StringUtils.isNotBlank(strCharge)) {
			c.setCharge(new BigDecimal(strCharge));
		}

		return c;
	}

	public String getFormatDate(Date date) {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String strDate = sdf.format(date);

		return strDate;

	}

}
